package nl.science.uva.pico.operator;

import nl.science.uva.pico.ProgramCounter;
import nl.science.uva.pico.Stack;
import nl.uva.science.pico.stacklanguage.types.LabelInstr;
import nl.uva.science.pico.stacklanguage.types.LabelInstrList;

/** 
 * Class Operator is the superclass of all operators. 
 * 
 * Defines the main shared functionality of all operators.
 * Operator subclasses will be polymorphic.   
 * It is not legal to instantiate an Operator; 
 * every Operator occurrence will be a subclass instance.
 *  
 * @author Ivo van Dongen, Karel Pieterson
 * @version 1.0
 */

public abstract class Operator {
	
	private Stack stack;
	private ProgramCounter programCounter;
	private LabelInstrList programListing;

    /** 
     * Create an Operator 
     * 
     * <p> Constructor is called by the subclasses
     */
	public Operator(Stack stack, ProgramCounter programCounter, LabelInstrList programListing) {
		this.stack = stack;
		this.programCounter = programCounter;
		this.programListing = programListing;
	}
	
    /** 
     * Jump to a label 
     * 
     * @param label: the label to jump to (integer value)
     * 
     * @throws IllegalStateException
     */
	protected void gotoLabel(Integer label) {
		for (int indexInListing = 0; indexInListing < programListing.getLength(); indexInListing++) {
			LabelInstr labelInstr = (LabelInstr) programListing.getChildAt(indexInListing);
			if (label.equals(labelInstr.getNatCon())) {
				programCounter.setCurrentLine(indexInListing);
				return;
			}
		}
		throw new IllegalStateException("Label " + label + " does not exist: " );
	}
	
	
    /** 
     * Perform does the operator specific work 
     * <p>Implemented by the specific subclass
     * 
     */
	public abstract void perform();


    /** 
     * Return the Operator's stack 
     * 
     */
	public Stack getStack() {
		return stack;
	}


    /** 
     * Return the Operator's program counter 
     * 
     */
	public ProgramCounter getProgramCounter() {
		return programCounter;
	}
}
